package com.ftcs.controller.common.service.impl;

import com.ftcs.controller.common.util.BizException;
import com.ftcs.controller.common.request.*;
import com.ftcs.controller.common.service.ActivitiService;
import com.ftcs.model.FinishedInstanceDTO;
import com.ftcs.model.PageInfo;
import com.ftcs.model.RunningProcess;
import com.ftcs.model.TodoTaskDTO;
import lombok.extern.slf4j.Slf4j;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.bpmn.model.FlowNode;
import org.activiti.bpmn.model.Process;
import org.activiti.bpmn.model.SequenceFlow;
import org.activiti.engine.*;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricProcessInstanceQuery;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.impl.identity.Authentication;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service(value = "activitiService")
public class ActivitiServiceImpl implements ActivitiService {
    @Autowired
    private IdentityService identityService;
    @Autowired
    private RuntimeService runtimeService;
    @Autowired
    private TaskService taskService;
    @Autowired
    HistoryService historyService;
    @Autowired
    private RepositoryService repositoryService;


    @Override
    public String startWorkFlow(StartWorkFlowRequest request) {

        identityService.setAuthenticatedUserId(request.getUserId());
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(request.getProDefName(), request.getBusinesskey(), request.getVariables());
        log.info("流程(流程执行对象实例)id=【{}】", processInstance.getId());
        log.info("流程实例id=【{}】", processInstance.getProcessInstanceId());
        log.info("流程定义id=【{}】", processInstance.getProcessDefinitionId());
        return processInstance.getId();
    }

    @Override
    public TodoTaskDTO listTodoTasks(TodoTasksRequest request) {

        List<Task> tasks = new ArrayList<>();
        PageInfo pageInfo = new PageInfo(request.getCurrent(), request.getPageSize());

        int firstrow = (request.getCurrent() - 1) * request.getPageSize();
        long count = 0L;
        if (Objects.nonNull(request.getUserId())) {
            //需要传入任务名称
            tasks = taskService.createTaskQuery()
                    .taskCandidateOrAssigned(request.getUserId())
                    .taskName(request.getTaskName())
                    .orderByTaskCreateTime().desc()
                    .listPage(firstrow, request.getPageSize());
            count = taskService.createTaskQuery()
                    .taskCandidateOrAssigned(request.getUserId())
                    .taskName(request.getTaskName()).count();
        } else if (Objects.nonNull(request.getUserGroup())) {
            tasks = taskService.createTaskQuery().taskCandidateGroup(request.getUserGroup()).listPage(firstrow, request.getPageSize());
            count = taskService.createTaskQuery().taskCandidateGroup(request.getUserGroup()).count();
        }
        pageInfo.setTotal((int) count);

        return TodoTaskDTO.builder().taskList(tasks).pageInfo(pageInfo).build();
    }

//    @Override
//    public int countTodoTasks(TodoTasksRequest request) {
//        long count = 0;
//        if (Objects.nonNull(request.getUserId())) {
//            count = taskService.createTaskQuery()
//                    .taskCandidateOrAssigned(request.getUserId())
//                    .taskName(request.getTaskName()).count();
//        } else if (Objects.nonNull(request.getUserGroup())) {
//            count = taskService.createTaskQuery().taskCandidateGroup(request.getUserGroup()).count();
//        }
//        return (int) count;
//    }

    @Override
    public List<Task> listFinishedTasks(TodoTasksRequest request) {


        return null;
    }

    @Override
    public FinishedInstanceDTO listFinishedProcessInstances(FinishedTasksRequest request) {
        PageInfo pageInfo = new PageInfo(request.getCurrent(), request.getPageSize());
        HistoricProcessInstanceQuery process = historyService.createHistoricProcessInstanceQuery()
                .processDefinitionKey(request.getProDefKey())
                .startedBy(request.getUserId())
                .finished();
        int total = (int) process.count();
        pageInfo.setTotal(total);
        int firstrow = (request.getCurrent() - 1) * request.getPageSize();
        List<HistoricProcessInstance> historicProInstanceList = process.listPage(firstrow, request.getPageSize());

        return FinishedInstanceDTO.builder().instanceList(historicProInstanceList).pageInfo(pageInfo).build();
    }


    @Override
    public String getBusinessKeyByTaskId(String taskId) {
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        String processInstanceId = task.getProcessInstanceId();
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        String businesskey = processInstance.getBusinessKey();
        return businesskey;
    }

    @Override
    public void submitTask(Submit2NextRequest request) {
        //评论信息
        if (Objects.nonNull(request.getComment())) {
            Task task = taskService.createTaskQuery().taskId(request.getTaskId()).singleResult();
            String processInstanceId = task.getProcessInstanceId();
            Authentication.setAuthenticatedUserId(request.getUserId());
            taskService.addComment(request.getTaskId(), processInstanceId, request.getComment());
        }
        //TODO 附件

        //任务声明（或者叫签收），没有指定代理人或者只指定了候选人获选人组时，需要先签收，从候选人中选择用户来签收
        taskService.claim(request.getTaskId(), request.getUserId());
        //任务完成
        taskService.complete(request.getTaskId(), request.getVariables());
        log.info("完成任务【{}】", request.getTaskId());
    }

    @Override
    public void revokeTask(String taskId) {
        HistoricTaskInstance task = historyService.createHistoricTaskInstanceQuery().taskId(taskId).singleResult();
        if (null == task) {
            throw new BizException("-10004", "无效任务ID[ " + taskId + " ]");
        }
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult();
        if (null == processInstance) {
            throw new BizException("-10004", "该流程已完成!无法回退");
        }

        // 获取流程定义对象
        BpmnModel bpmnModel = repositoryService.getBpmnModel(task.getProcessDefinitionId());
        Process process = bpmnModel.getProcesses().get(0);

        List<Task> taskList = taskService.createTaskQuery().processInstanceId(processInstance.getId()).list();

        FlowNode sourceNode = (FlowNode) process.getFlowElement(task.getTaskDefinitionKey());
        taskList.forEach(obj -> {
            FlowNode currentNode = (FlowNode) process.getFlowElement(obj.getTaskDefinitionKey());
            // 获取原本流程连线
            List<SequenceFlow> outComingSequenceFlows = currentNode.getOutgoingFlows();

            // 配置反转流程连线
            SequenceFlow sequenceFlow = new SequenceFlow();
            sequenceFlow.setTargetFlowElement(sourceNode);
            sequenceFlow.setSourceFlowElement(currentNode);
            sequenceFlow.setId("callback-flow");

            List<SequenceFlow> newOutComingSequenceFlows = new ArrayList<>();
            newOutComingSequenceFlows.add(sequenceFlow);
            currentNode.setOutgoingFlows(newOutComingSequenceFlows);

            // 配置任务审批人
            Map<String, Object> variables = new HashMap<>(1);
//            variables.put("assignee", UserEntityService.getCurrentUserEntity().getUserId());
            // 完成任务
            taskService.complete(obj.getId(), variables);
            // 复原流程
            currentNode.setOutgoingFlows(outComingSequenceFlows);
        });

        // 更新流程状态
//        updateAuditStatus(processInstance.getProcessInstanceId());
    }

//    /**
//     * 获取流程审核状态
//     *
//     * @param processInstanceId
//     * @return
//     */
//    public int updateAuditStatus(String processInstanceId) {
//
//        String auditCode = "";
//        HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
//        if (null != historicProcessInstance) {
//
//            // 流程已完成
//            if (null != historicProcessInstance.getEndTime()) {
//                ProcessAuditStatus processAuditStatus = processAuditStatusMapper.findByProcessDefinitionIdAndUserTask(historicProcessInstance.getProcessDefinitionId(), WorkFlowConfiguration.PROCESS_END_EVENT_FLAG);
//                if (null != processAuditStatus) {
//                    auditCode = processAuditStatus.getAuditCode();
//                }
//            } else {
//                // 流程未完成
//                List<HistoricTaskInstance> taskList = historyService.createHistoricTaskInstanceQuery().processInstanceId(processInstanceId).orderByTaskCreateTime().desc().list();
//                if (!taskList.isEmpty()) {
//                    HistoricTaskInstance historicTaskInstance = taskList.get(0);
//                    ProcessAuditStatus processAuditStatus = processAuditStatusMapper.findByProcessDefinitionIdAndUserTask(historicTaskInstance.getProcessDefinitionId(), historicTaskInstance.getTaskDefinitionKey());
//                    if (null != processAuditStatus) {
//                        auditCode = processAuditStatus.getAuditCode();
//                    }
//                }
//            }
//        }
//
//        // 更新业务
//        return commonWorkEntityService.updateAuditStatus(historicProcessInstance.getBusinessKey(), auditCode);
//    }

    @Override
    public void getTraceImage() {
//        ActivitiController.traceProcess
    }

    @Override
    public List<RunningProcess> listLaunchedProcessInstances() {
        return null;
    }

    @Override
    public List<RunningProcess> listInvolvingProcessInstances(InvovedProcessInstanceRequest request) {
        List<ProcessInstance> processInstanceList = runtimeService.createProcessInstanceQuery()
                .processDefinitionKey(request.getProcessDefKey())
                .involvedUser(request.getUserId())
                .listPage(request.getFirstRow(), request.getPageSize());
        List<RunningProcess> list = processInstanceList.stream().map(instance -> {
            RunningProcess process = new RunningProcess();
            // 有子流程，若进入子流程当前流程实例的活动节点activitId为null，activitiId活动节点的id,流程模板中指定
            if (instance.getActivityId() == null) {
                String mainInstanceId = instance.getProcessInstanceId();
                // 子流程的活动节点
                String subActiveId = runtimeService.createExecutionQuery().parentId(mainInstanceId).singleResult().getActivityId();
                String subExeId = runtimeService.createExecutionQuery().parentId(mainInstanceId).singleResult().getId();
                process.setActivityId(subActiveId);
                // System.out.println(taskservice.createTaskQuery().executionId(sonexeid).singleResult().getName());
            } else {
                process.setActivityId(instance.getActivityId());
            }

            process.setBusinessKey(instance.getBusinessKey());
            process.setExecutionId(instance.getId());
            process.setProcessInstanceId(instance.getProcessInstanceId());
            return process;
        }).collect(Collectors.toList());
        return list;
    }
}
